package cn.maihe.elg.operation.service.order;

import cn.maihe.elg.operation.model.enums.AcceptOrderStatus;
import cn.maihe.elg.operation.model.enums.ApplyOrderStatus;
import cn.maihe.elg.operation.model.enums.GuaranteeStatus;
import cn.maihe.elg.operation.model.vo.order.AcceptOrderStatusAuditVO;
import cn.maihe.elg.operation.repository.entity.*;
import cn.maihe.elg.operation.repository.mapper.AcceptOrderInfoMapper;
import cn.maihe.elg.operation.service.BaseDaoService;
import cn.maihe.elg.operation.service.business.ExchangeCenterService;
import cn.maihe.elg.operation.service.guarantee.GuaranteeService;
import cn.maihe.elg.operation.utils.ElgLogger;
import cn.maihe.framework.starter.mybatis.dao.MybatisDaoImpl;
import cn.maihe.framework.starter.mybatis.mapper.PlusEntityWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * @Description
 * @Author WJH
 * @Date 2021/04/29
 */
@Service
@Slf4j
public class RevokeOrderInfoService extends BaseDaoService<RevokeOrderInfo> {
    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;
    @Resource
    private ExchangeCenterService exchangeCenterService;
    @Resource
    private GuaranteeService guaranteeService;
    @Resource
    ApplyOrderInfoService applyOrderInfoService;
//    @Resource
//    private GuarantorRevokeNoticeChannelService revokeNoticeChannelService;


    public boolean existsRevokeNo(long centerId, long orgId, String revokeNo) {
        return this.exists(RevokeOrderInfoCondition.builder().andCenterIdEq(centerId).andOrgIdEq(orgId).andRevokeNoEq(revokeNo).build());
    }

    /**
     * 查询某标段下保函是否撤销过记录
     */
    public List<RevokeGuaranteeData> getRevokeGuaranteeData(String sectionCode, String guaranteeNo) {
        return MybatisDaoImpl.run().selectList(RevokeGuaranteeData.builder().sectionCode(sectionCode).guaranteeNo(guaranteeNo).build());
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveRevokeOrderInfo(AcceptOrderInfoDO acceptOrderInfoDO, RevokeOrderInfo revokeOrderInfo, List<RevokeGuaranteeData> revokeGuaranteeDataList) {
        MybatisDaoImpl.run().insert(revokeOrderInfo);
        revokeGuaranteeDataList.forEach(item -> {
            item.setRevokeOrderId(revokeOrderInfo.getId());
        });
        MybatisDaoImpl.run().insertBatch(revokeGuaranteeDataList);
        MybatisDaoImpl.run().updateById(acceptOrderInfoDO);
//        revokeOrder(revokeOrderInfo,revokeGuaranteeDataList);//todo 未完成未测试 自动退保
    }

    @Transactional(rollbackFor = Exception.class)
    public RevokeOrderInfo saveRevokeOrderInfo(RevokeOrderInfo revokeOrderInfo, List<RevokeOrderAttachmentDO> attachmentDOS, AcceptOrderInfoDO acceptOrderInfoDO) {
        {
            RevokeOrderInfo dbInfo = getRevokeOrderInfo(revokeOrderInfo.getCenterId(), revokeOrderInfo.getOrgId(), revokeOrderInfo.getRevokeNo());
            if (dbInfo == null) {
                this.insert(revokeOrderInfo);
                if (attachmentDOS != null) {
                    MybatisDaoImpl.run().insertBatch(attachmentDOS);
                }
            } else {
                revokeOrderInfo.setId(dbInfo.getId());
                this.updateById(revokeOrderInfo);
                MybatisDaoImpl.run().delete(RevokeOrderAttachmentDOCondition.builder().andRevokeOrderIdEq(dbInfo.getId()).build());
                if (attachmentDOS != null) {
                    attachmentDOS.forEach(item -> item.setRevokeOrderId(dbInfo.getId()));
                    MybatisDaoImpl.run().insertBatch(attachmentDOS);
                }

            }
            MybatisDaoImpl.run().updateById(acceptOrderInfoDO);
            return revokeOrderInfo;
        }
    }

    private void revokeOrder(RevokeOrderInfo revokeOrderInfo, List<RevokeGuaranteeData> revokeGuaranteeDataList) {
        CompletableFuture.runAsync(() -> {
            try {
                StringBuffer sb = new StringBuffer();
                String acceptOrderNo = "";
                for (RevokeGuaranteeData data : revokeGuaranteeDataList) {
                    sb.append(data.getGuaranteeNo() + ",");
                    ApplyOrderInfoDO applyOrderInfo = applyOrderInfoService.getByGuaranteeNo(data.getGuaranteeNo());
                    AcceptOrderInfoDO orderInfoDO = acceptOrderInfoService.getByCenterOrderId(applyOrderInfo.getCenterId(), applyOrderInfo.getOrgId(), applyOrderInfo.getCenterOrderId());
                    acceptOrderNo = orderInfoDO.getAcceptOrderNo();
                    GuaranteeDOCondition condition = GuaranteeDOCondition.builder().andOrgIdEq(applyOrderInfo.getOrgId())
                            .andCenterIdEq(applyOrderInfo.getCenterId()).andGuaranteeNoEq(data.getGuaranteeNo());
                    GuaranteeDO guaranteeDO = guaranteeService.selectOne(condition.build());

                    guaranteeDO.setGuaranteeStatus(GuaranteeStatus.FINISH_UNPROTECT.getStatus());
                    guaranteeDO.setRevokeTime(new Date());

                    applyOrderInfo.setStatus(ApplyOrderStatus.CANCEL.getStatus());

                    orderInfoDO.setRevokeFlag(2);
                    orderInfoDO.setStatus(AcceptOrderStatus.CANCEL.getStatus());

                    MybatisDaoImpl.run().updateById(orderInfoDO);
                    MybatisDaoImpl.run().updateById(applyOrderInfo);
                    MybatisDaoImpl.run().updateById(guaranteeDO);

                    Map params = new HashMap();
                    params.put("bidCustomerId", orderInfoDO.getBidCustomerId());
                    params.put("projectId", orderInfoDO.getProjectId());
                    MybatisDaoImpl.of(AcceptOrderInfoMapper.class).updateBySql("reduceGuaranteeCount", params);

                    data.setProcessStatus(1);
                }
                revokeOrderInfo.setStatus(1);

                this.updateById(revokeOrderInfo);
                MybatisDaoImpl.run().updateBatchById(revokeGuaranteeDataList);

                sb.deleteCharAt(sb.length() - 1);

//                GuarantorRevokeNoticeReqDTO reqDTO = new GuarantorRevokeNoticeReqDTO();
//                reqDTO.setPolicyNo(sb.toString());
//                reqDTO.setStatus("7");
//                reqDTO.setMsg("撤销完成");
//                FollowBaseRespDTO respDTO = revokeNoticeChannelService.doRequest(reqDTO);
//                Assert.notNull(respDTO, "响应报文不能为空");
//                if (!"200".equals(respDTO.getCode())) {
//                    throw new RuntimeException("响应码非成功[" + respDTO.getCode() + ":" + respDTO.getMsg() + "]");
//                }
                log.info("保函编号[{}] >> 撤销结果回调通知成功", sb.toString());
            } catch (Exception e) {
                ElgLogger.info(log, log -> log.info("退保编号[{}] >> 异步退保结果异常：{}", revokeOrderInfo.getId(), e.getMessage(), e));
            }
        });
    }


    public void audit(AcceptOrderStatusAuditVO vo, String acceptOrderNo, String guaranteeNo) {
        RevokeGuaranteeData revokeGuaranteeData = MybatisDaoImpl.run().selectOne(RevokeGuaranteeDataCondition.builder().andGuaranteeNoEq(guaranteeNo).andProcessStatusEq(0).build());

        if (vo.getAuditStatus() == 1) {
            if (revokeGuaranteeData != null) {
                RevokeOrderInfo revokeOrderInfo = this.selectById(revokeGuaranteeData.getRevokeOrderId());
                List<RevokeGuaranteeData> a = new ArrayList<>();
                a.add(revokeGuaranteeData);
                this.revokeOrder(revokeOrderInfo, a);
            }
        } else {
            //todo 审批不通过
            if (revokeGuaranteeData != null) {
                RevokeOrderInfo revokeOrderInfo = this.selectById(revokeGuaranteeData.getRevokeOrderId());
                List<RevokeGuaranteeData> a = new ArrayList<>();
                a.add(revokeGuaranteeData);
                this.revokeOrderRejust(vo, revokeOrderInfo, a);
            }

        }

    }

    private void revokeOrderRejust(AcceptOrderStatusAuditVO vo, RevokeOrderInfo revokeOrderInfo, List<RevokeGuaranteeData> revokeGuaranteeDataList) {
        CompletableFuture.runAsync(() -> {
            try {
                StringBuffer sb = new StringBuffer();
                String acceptOrderNo = "";
                for (RevokeGuaranteeData data : revokeGuaranteeDataList) {
                    sb.append(data.getGuaranteeNo() + ",");
                    ApplyOrderInfoDO applyOrderInfo = applyOrderInfoService.getByGuaranteeNo(data.getGuaranteeNo());
                    AcceptOrderInfoDO orderInfoDO = acceptOrderInfoService.getByCenterOrderId(applyOrderInfo.getCenterId(), applyOrderInfo.getOrgId(), applyOrderInfo.getCenterOrderId());

                    orderInfoDO.setRevokeFlag(0);
                    MybatisDaoImpl.run().updateById(orderInfoDO);

                    data.setProcessStatus(2);
                }
                revokeOrderInfo.setStatus(2);

                this.updateById(revokeOrderInfo);
                MybatisDaoImpl.run().updateBatchById(revokeGuaranteeDataList);

                sb.deleteCharAt(sb.length() - 1);

//                GuarantorRevokeNoticeReqDTO reqDTO = new GuarantorRevokeNoticeReqDTO();
//                reqDTO.setPolicyNo(sb.toString());
//                reqDTO.setStatus("0");
//                reqDTO.setMsg(vo.getAuditRemark());
//                FollowBaseRespDTO respDTO = revokeNoticeChannelService.doRequest(reqDTO);
//                Assert.notNull(respDTO, "响应报文不能为空");
//                if (!"200".equals(respDTO.getCode())) {
//                    throw new RuntimeException("响应码非成功[" + respDTO.getCode() + ":" + respDTO.getMsg() + "]");
//                }
                log.info("保函编号[{}] >> 撤销结果回调通知成功", sb.toString());
            } catch (Exception e) {
                ElgLogger.info(log, log -> log.info("退保编号[{}] >> 异步退保结果异常：{}", revokeOrderInfo.getId(), e.getMessage(), e));
            }
        });
    }

    public RevokeOrderInfo getRevokeOrderInfo(Long centerId, Long orgId, String revokeNo) {
        PlusEntityWrapper<RevokeOrderInfo> condition = RevokeOrderInfoCondition.builder()
                .andCenterIdEq(centerId).andOrgIdEq(orgId).andRevokeNoEq(revokeNo).build();
        return this.selectOne(condition);
    }

    public RevokeOrderInfo saveRevokeOrderInfo(RevokeOrderInfo revokeOrderInfo) {
        RevokeOrderInfo dbInfo = getRevokeOrderInfo(revokeOrderInfo.getCenterId(), revokeOrderInfo.getOrgId(), revokeOrderInfo.getRevokeNo());
        if (dbInfo == null) {
            this.insert(revokeOrderInfo);
        } else {
            revokeOrderInfo.setId(dbInfo.getId());
            this.updateById(revokeOrderInfo);
        }
        return revokeOrderInfo;
    }
}
